package com.gitee.tanmingjian.httptunnel.handler;


import com.gitee.tanmingjian.httptunnel.core.HttpTunnelService;
import com.gitee.tanmingjian.httptunnel.core.bean.QueryParam;
import org.springframework.http.MediaType;
import org.springframework.http.codec.multipart.FormFieldPart;
import org.springframework.http.codec.multipart.Part;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

import java.io.IOException;
import java.util.Map;
import java.util.stream.Collectors;

public class ReactiveHttpTunnelHandler {

    private final HttpTunnelService httpTunnelService;
    private final String basePath;

    public ReactiveHttpTunnelHandler(String basePath, HttpTunnelService httpTunnelService) {
        this.basePath = basePath;
        this.httpTunnelService = httpTunnelService;
    }


    public Mono<ServerResponse> index(ServerRequest request) {
        String indexHtml = null;
        try {
            indexHtml = httpTunnelService.getIndexHtml(basePath);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return ServerResponse.ok().contentType(MediaType.TEXT_HTML).bodyValue(indexHtml);
    }

    public Mono<ServerResponse> post(ServerRequest request) {
        Mono<MultiValueMap<String, String>> formData = request.formData();
        Mono<MultiValueMap<String, Part>> multipartData = request.multipartData();
        Map<String, String> pathVariables = request.pathVariables();
        String sessionId = pathVariables.getOrDefault("sessionId", "default");
        return Mono.zip(formData, multipartData).flatMap(tuple -> {
            MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
            params.putAll(tuple.getT1());
            tuple.getT2().forEach((key, values) -> {
                if (!CollectionUtils.isEmpty(values)) {
                    params.put(key, values.stream()
                            .map((value) -> value instanceof FormFieldPart ? ((FormFieldPart) value).value() : value.toString())
                            .collect(Collectors.toList())
                    );
                }
            });

            QueryParam queryParam = new QueryParam();
            queryParam.setHost(params.getFirst("host"));
            queryParam.setPort(params.getFirst("port"));
            queryParam.setLogin(params.getFirst("login"));
            queryParam.setPassword(params.getFirst("password"));
            queryParam.setDb(params.getFirst("db"));
            queryParam.setActn(params.getFirst("actn"));
            queryParam.setEncodeBase64(params.getFirst("encodeBase64"));
            queryParam.setQ(params.get("q[]"));

            return ServerResponse.ok().contentType(MediaType.APPLICATION_OCTET_STREAM).bodyValue(httpTunnelService.process(queryParam, sessionId));
        });
    }

}
